有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java流收集器。toMap值是一个集合

我想使用Java流运行POJO列表,例如下面的列表List<A>,并将其转换为映射Map<String, Set<String>>

例如,A类是:

class A {
    public String name;
    public String property;
}

我编写了下面的代码,将值收集到映射Map<String, String>

final List<A> as = new ArrayList<>();
// the list as is populated ...

// works if there are no duplicates for name
final Map<String, String> m = as.stream().collect(Collectors.toMap(x -> x.name, x -> x.property));

但是,因为可能有多个POJO具有相同的name,所以我希望映射的值是aSet。同一个键name的所有property字符串都应该进入同一个集合

如何做到这一点

// how do i create a stream such that all properties of the same name get into a set under the key name
final Map<String, Set<String>> m = ???

共 (4) 个答案

  1. # 1 楼答案

    相同但不同

    Map<String, Set<String>> m = new HashMap<>();
    
    as.forEach(a -> {
        m.computeIfAbsent(a.name, v -> new HashSet<>())
                .add(a.property);
        });
    
  2. # 2 楼答案

    此外,还可以使用收集器的合并功能选项。toMap函数 收藏家。toMap(键映射器、值映射器、合并函数)如下所示:

    final Map<String, String> m = as.stream()
                                    .collect(Collectors.toMap(
                                              x -> x.name, 
                                              x -> x.property,
                                              (property1, property2) -> property1+";"+property2);
    
  3. # 3 楼答案

    @Nevay的答案使用groupingBy肯定是正确的,但也可以通过toMap添加mergeFunction作为第三个参数来实现:

    as.stream().collect(Collectors.toMap(x -> x.name, 
        x -> new HashSet<>(Arrays.asList(x.property)), 
        (x,y)->{x.addAll(y);return x;} ));
    

    这段代码将数组映射到一个映射,其中键为x.name,值为HashSet,值为x.property。当存在重复的键/值时,将调用第三个参数合并函数来合并两个哈希集

    如果使用Apache公共库,也可以使用它们的SetUtils::union作为合并

  4. # 4 楼答案

    groupingBy正是您想要的:

    import static java.util.stream.Collectors.*;
    ...
    as.stream().collect(groupingBy((x) -> x.name, mapping((x) -> x.property, toSet())));